package com.alg.local.gateway.util;

import com.alg.local.gateway.config.GatewayConstant;
import com.alg.local.gateway.entity.AuthTypeProps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.redisson.api.RBucket;
import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.redisson.client.codec.StringCodec;
import org.slf4j.MDC;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.support.ServerWebExchangeUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.server.ServerWebExchange;

import javax.servlet.http.HttpServletRequest;
import java.security.PrivateKey;
import java.util.HashMap;
import java.util.Map;

/**
 * @author al
 * @date 2022/5/31 14:50
 * @description
 */
@Aspect
@Component
@Slf4j
public class CheckTempTokenAsp {

    @Autowired
    RedissonClient redissonClient;
    @Autowired
    AuthTypeProps props;

    @Pointcut("@annotation(checkToken)")
    public void doCheckTokenCut(CheckToken checkToken) {
    }

    @Around(value = "doCheckTokenCut(checkToken)", argNames = "joinPoint,checkToken")
    public Object doAround(ProceedingJoinPoint joinPoint, CheckToken checkToken) throws Throwable {
        Object[] args = joinPoint.getArgs();
        if (args != null) {
            for (Object arg : args) {
                if (arg instanceof ServerWebExchange) {
                    ServerWebExchange t = (ServerWebExchange) arg;
                    String token = t.getRequest().getHeaders().getFirst("token");
                    if (StringUtils.isEmpty(token)) {
                        throw new Exception("Unauthorized access");
                    }
                    RBucket<String> redisToken = redissonClient.getBucket(GatewayConstant.TEMP_TOKEN, new StringCodec());
                    if (StringUtils.isEmpty(redisToken.get())) {
                        throw new Exception("Unauthorized access");
                    }
                    if (!redisToken.get().equals(token)) {
                        throw new Exception("Unauthorized access");
                    }

                    RMap<String, String> simpleMapTest = redissonClient.getMap(GatewayConstant.RSA_KEY_MAP, new StringCodec());
                    String priKey = simpleMapTest.get(GatewayConstant.RSA_PRI_KEY);
                    PrivateKey privateKey = AsymmetricEncryptionUtil.getPrivateKey(priKey);
                    String decrypt = AsymmetricEncryptionUtil.build("RSA").setPrivateKey(privateKey).decrypt(token);
                    if (props.getGlobalToken().getSysUser().equals(decrypt)) {
                        return joinPoint.proceed();
                    }
                }
            }
        }
        throw new Exception("Unauthorized access");
    }

}
